package com.example.vaultmysql.service;

import com.example.vaultmysql.entity.DatabaseConfig;
import com.example.vaultmysql.repository.DatabaseConfigRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 数据库配置服务
 * 负责数据库配置的CRUD操作
 * 
 * @author System
 * @version 1.0.0
 */
@Slf4j
@Service
@Transactional
public class DatabaseConfigService {

    @Autowired
    private DatabaseConfigRepository databaseConfigRepository;

    @Autowired
    private DatabaseConnectionService databaseConnectionService;

    /**
     * 获取所有数据库配置
     */
    public List<DatabaseConfig> getAllDatabaseConfigs() {
        return databaseConfigRepository.findAll();
    }

    /**
     * 分页获取数据库配置
     */
    public Page<DatabaseConfig> getDatabaseConfigs(Pageable pageable) {
        return databaseConfigRepository.findAll(pageable);
    }

    /**
     * 根据ID获取数据库配置
     */
    public Optional<DatabaseConfig> getDatabaseConfigById(Long id) {
        return databaseConfigRepository.findById(id);
    }

    /**
     * 根据名称获取数据库配置
     */
    public Optional<DatabaseConfig> getDatabaseConfigByName(String name) {
        return databaseConfigRepository.findByName(name);
    }

    /**
     * 获取所有启用的数据库配置
     */
    public List<DatabaseConfig> getEnabledDatabaseConfigs() {
        return databaseConfigRepository.findByEnabledTrue();
    }

    /**
     * 搜索数据库配置
     */
    public List<DatabaseConfig> searchDatabaseConfigs(String keyword) {
        return databaseConfigRepository.findByNameContainingIgnoreCaseOrHostContainingIgnoreCase(keyword, keyword);
    }

    /**
     * 创建数据库配置
     */
    public DatabaseConfig createDatabaseConfig(DatabaseConfig config) {
        // 验证配置
        validateDatabaseConfig(config);
        
        // 检查名称是否已存在
        if (databaseConfigRepository.existsByName(config.getName())) {
            throw new IllegalArgumentException("数据库配置名称已存在: " + config.getName());
        }
        
        // 设置创建时间
        config.setCreatedAt(LocalDateTime.now());
        config.setUpdatedAt(LocalDateTime.now());
        
        DatabaseConfig savedConfig = databaseConfigRepository.save(config);
        log.info("创建数据库配置: {}", savedConfig.getName());
        
        return savedConfig;
    }

    /**
     * 更新数据库配置
     */
    public DatabaseConfig updateDatabaseConfig(Long id, DatabaseConfig config) {
        DatabaseConfig existingConfig = databaseConfigRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("数据库配置不存在: " + id));
        
        // 验证配置
        validateDatabaseConfig(config);
        
        // 检查名称是否与其他配置冲突
        if (!existingConfig.getName().equals(config.getName()) && 
            databaseConfigRepository.existsByName(config.getName())) {
            throw new IllegalArgumentException("数据库配置名称已存在: " + config.getName());
        }
        
        // 更新字段
        existingConfig.setName(config.getName());
        existingConfig.setHost(config.getHost());
        existingConfig.setPort(config.getPort());
        existingConfig.setSchemaName(config.getSchemaName());
        existingConfig.setVaultPath(config.getVaultPath());
        existingConfig.setEnabled(config.getEnabled());
        existingConfig.setUpdatedAt(LocalDateTime.now());
        
        DatabaseConfig savedConfig = databaseConfigRepository.save(existingConfig);
        log.info("更新数据库配置: {}", savedConfig.getName());
        
        // 如果配置发生变化，刷新连接池
        databaseConnectionService.refreshDataSource(savedConfig.getName());
        
        return savedConfig;
    }

    /**
     * 删除数据库配置
     */
    public void deleteDatabaseConfig(Long id) {
        DatabaseConfig config = databaseConfigRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("数据库配置不存在: " + id));
        
        // 关闭相关连接池
        databaseConnectionService.closeDataSource(config.getName());
        
        databaseConfigRepository.deleteById(id);
        log.info("删除数据库配置: {}", config.getName());
    }

    /**
     * 启用/禁用数据库配置
     */
    public DatabaseConfig toggleDatabaseConfig(Long id, boolean enabled) {
        DatabaseConfig config = databaseConfigRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("数据库配置不存在: " + id));
        
        config.setEnabled(enabled);
        config.setUpdatedAt(LocalDateTime.now());
        
        DatabaseConfig savedConfig = databaseConfigRepository.save(config);
        log.info("{}数据库配置: {}", enabled ? "启用" : "禁用", savedConfig.getName());
        
        // 如果禁用，关闭连接池
        if (!enabled) {
            databaseConnectionService.closeDataSource(savedConfig.getName());
        }
        
        return savedConfig;
    }

    /**
     * 批量创建数据库配置
     */
    public List<DatabaseConfig> createDatabaseConfigs(List<DatabaseConfig> configs) {
        for (DatabaseConfig config : configs) {
            validateDatabaseConfig(config);
            
            // 检查名称是否已存在
            if (databaseConfigRepository.existsByName(config.getName())) {
                throw new IllegalArgumentException("数据库配置名称已存在: " + config.getName());
            }
            
            config.setCreatedAt(LocalDateTime.now());
            config.setUpdatedAt(LocalDateTime.now());
        }
        
        List<DatabaseConfig> savedConfigs = databaseConfigRepository.saveAll(configs);
        log.info("批量创建数据库配置: {} 个", savedConfigs.size());
        
        return savedConfigs;
    }

    /**
     * 获取数据库配置统计信息
     */
    public DatabaseConfigStats getStats() {
        long totalCount = databaseConfigRepository.count();
        long enabledCount = databaseConfigRepository.countByEnabledTrue();
        long disabledCount = totalCount - enabledCount;
        
        return new DatabaseConfigStats(totalCount, enabledCount, disabledCount);
    }

    /**
     * 验证数据库配置
     */
    private void validateDatabaseConfig(DatabaseConfig config) {
        if (config.getName() == null || config.getName().trim().isEmpty()) {
            throw new IllegalArgumentException("数据库名称不能为空");
        }
        
        if (config.getHost() == null || config.getHost().trim().isEmpty()) {
            throw new IllegalArgumentException("数据库主机不能为空");
        }
        
        if (config.getPort() == null || config.getPort() <= 0 || config.getPort() > 65535) {
            throw new IllegalArgumentException("数据库端口必须在1-65535之间");
        }
        
        if (config.getSchemaName() == null || config.getSchemaName().trim().isEmpty()) {
            throw new IllegalArgumentException("数据库Schema名称不能为空");
        }
        
        if (config.getVaultPath() == null || config.getVaultPath().trim().isEmpty()) {
            throw new IllegalArgumentException("Vault路径不能为空");
        }
        
        // 验证名称格式（只允许字母、数字、下划线、连字符）
        if (!config.getName().matches("^[a-zA-Z0-9_-]+$")) {
            throw new IllegalArgumentException("数据库名称只能包含字母、数字、下划线和连字符");
        }
        
        // 验证Vault路径格式
        if (!config.getVaultPath().startsWith("/")) {
            throw new IllegalArgumentException("Vault路径必须以/开头");
        }
    }

    /**
     * 数据库配置统计信息
     */
    public static class DatabaseConfigStats {
        private final long totalCount;
        private final long enabledCount;
        private final long disabledCount;
        
        public DatabaseConfigStats(long totalCount, long enabledCount, long disabledCount) {
            this.totalCount = totalCount;
            this.enabledCount = enabledCount;
            this.disabledCount = disabledCount;
        }
        
        public long getTotalCount() { return totalCount; }
        public long getEnabledCount() { return enabledCount; }
        public long getDisabledCount() { return disabledCount; }
        public double getEnabledPercentage() { 
            return totalCount > 0 ? (double) enabledCount / totalCount * 100 : 0; 
        }
    }
}